package com.bigbirdmed.cloud.common.core.util;

import com.google.common.collect.Lists;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.commons.lang3.RandomStringUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 全局帮助类
 *
 * @author Administrator
 */
public class Utilities {

    private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(nThreads));
    }

    /**
     * 验证数值是否大于0
     *
     * @param id 数值
     * @return 是否大于0
     */
    public static boolean isValidId(Number id) {
        return id != null && id.longValue() > 0;
    }

    public static List<Long> splitToLong(String str) {
        List<Long> result = Lists.newArrayList();
        if (StringUtils.isNotBlank(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, ",")) {
                if (StringUtils.isNotBlank(value)) {
                    try {
                        result.add(Long.parseLong(value));
                    } catch (NumberFormatException e) {
                    }
                }
            }
        }
        return result;
    }

    public static List<String> splitToString(String str) {
        List<String> result = Lists.newArrayList();
        if (StringUtils.isNotBlank(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, ",")) {
                if (StringUtils.isNotBlank(value)) {
                    result.add(value);
                }
            }
        }
        return result;
    }

    public static List<String> splitToString(String str, String c) {
        List<String> result = Lists.newArrayList();
        if (StringUtils.isNotBlank(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, c)) {
                if (StringUtils.isNotBlank(value)) {
                    result.add(value);
                }
            }
        }
        return result;
    }

    public static List<String> distinctStringList(List<String> srcList) {
        List<String> result = new ArrayList<>();
        for (String src : srcList) {
            if (!result.contains(src)) {
                result.add(src);
            }
        }
        return result;
    }

    /**
     * srcList是否完全包含findList列表
     *
     * @param srcList
     * @param findList
     * @return
     */
    public static boolean isContainsList(List<String> srcList, List<String> findList) {
        for (String findStr : findList) {
            if (!isContainsString(srcList, findStr)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断fieldVals列表中是否有包含
     *
     * @param fieldVals
     * @param q
     * @return
     */
    public static boolean isContainsString(List<String> fieldVals, String q) {
        for (String fieldVal : fieldVals) {
            if (fieldVal.toUpperCase().equals(q.toUpperCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成UUID
     *
     * @return
     */
    public static String getUuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String createOrderNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String orderNo = sdf.format(new Date()) + RandomStringUtils.random(6, false, true);
        return orderNo;
    }

    /**
     * md5
     *
     * @param src
     * @return
     * @throws Exception
     */
    public static String getMD5(String src) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(src.getBytes());
            byte[] hash = md.digest();
            StringBuilder secpwd = new StringBuilder();
            for (int i = 0; i < hash.length; i++) {
                int v = hash[i] & 0xFF;
                if (v < 16) {
                    secpwd.append(0);
                }
                secpwd.append(Integer.toString(v, 16));
            }
            return secpwd.toString();
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 生成随机位数的数字验证码
     *
     * @param length
     * @return
     */
    public static String getValidCode(int length) {
        Random r = new Random();
        int ran = r.nextInt((int) Math.pow(10, length));
        String str = String.format("%0" + length + "d", ran);
        return str;
    }

    public static String getSha(String sha, String shaType) {
        if (StringUtils.isEmpty(sha) || 0 == sha.length() || StringUtils.isEmpty(shaType)) {
            return null;
        }
        try {
            MessageDigest md = MessageDigest.getInstance(shaType);
            md.update(sha.getBytes("UTF-8"));

            byte[] result = md.digest();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < result.length; i++) {
                sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
            }

            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static Long getMapLongVal(Map<String, Object> valMap, String key) {
        return getMapStringVal(valMap, key) != null ? Long.parseLong(valMap.get(key).toString()) : null;
    }

    public static Double getMapDoubleVal(Map<String, Object> valMap, String key) {
        return getMapStringVal(valMap, key) != null ? Double.parseDouble(valMap.get(key).toString()) : 0L;
    }

    public static String getMapStringVal(Map<String, Object> valMap, String key) {
        String result = null;
        if (valMap.get(key) != null && !"null".equals(valMap.get(key).toString().trim())) {
            result = valMap.get(key).toString();
        }
        return result;
    }

    public static List<Long> getMapListLongVal(Map<String, Object> valMap, String key) {
        Object obj = valMap.get(key);
        List<Long> result = new ArrayList<>();
        if (obj instanceof List) {
            List tmpList = (List) obj;
            tmpList.forEach(e -> {
                if (e instanceof Integer) {
                    result.add(((Integer) e).longValue());
                } else if (e instanceof Long) {
                    result.add((Long) e);
                }
            });
        }
        return result;
    }

    public static List<Integer> getMapListIntegerVal(Map<String, Object> valMap, String key) {
        Object obj = valMap.get(key);
        List<Integer> result = new ArrayList<>();
        if (obj instanceof List) {
            List tmpList = (List) obj;
            tmpList.forEach(e -> {
                if (e instanceof Integer) {
                    result.add((Integer) e);
                } else if (e instanceof Long) {
                    result.add(((Long) e).intValue());
                }
            });
        }
        return result;
    }

    public static String getOrderNO() {
        String data = new SimpleDateFormat("yyMMddHHmmsss").format(Calendar.getInstance().getTime());
        int ran = new Random().nextInt(100);
        if (ran < 10) {
            return data + "0" + ran;
        } else {
            return data + ran;
        }
    }

    public static double getRoundHalfUp(double d, int num) {
        BigDecimal b = new BigDecimal(d);
        return b.setScale(num, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double getRoundHalfUp(BigDecimal bg, int num) {
        return bg.setScale(num, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static String getBigDecimalStrVal(BigDecimal bg, int num) {
        return bg.setScale(num, BigDecimal.ROUND_HALF_UP).toString();
    }

    public static List<String> split(String str, String separator) {
        List<String> result = new ArrayList<String>();

        if (!StringUtils.isEmpty(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, separator)) {
                if (!StringUtils.isEmpty(value)) {
                    result.add(value);
                }
            }
        }
        return result;
    }

    public static List<Long> splitLong(String str, String separator) {
        List<Long> result = new ArrayList<Long>();

        if (!StringUtils.isEmpty(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, separator)) {
                if (!StringUtils.isEmpty(value)) {
                    try {
                        result.add(Long.parseLong(value));
                    } catch (NumberFormatException e) {
                    }
                }
            }
        }

        return result;
    }

    public static List<Integer> splitInteger(String str, String separator) {
        List<Integer> result = new ArrayList<Integer>();

        if (!StringUtils.isEmpty(str)) {
            for (String value : org.springframework.util.StringUtils.split(str, separator)) {
                if (!StringUtils.isEmpty(value)) {
                    try {
                        result.add(Integer.parseInt(value));
                    } catch (NumberFormatException e) {
                    }
                }
            }
        }

        return result;
    }

    /**
     * 判断是否是数字类型
     *
     * @param val
     * @return
     */
    public static boolean isDigital(String val) {
        try {
            new BigDecimal(val);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static Integer getMapIntegerVal(Map<String, Object> valMap, String key) {
        return getMapStringVal(valMap, key) != null ? Integer.parseInt(valMap.get(key).toString()) : null;
    }

    public static BigDecimal getMapDigitalVal(Map<String, Object> valMap, String key) {
        return getMapStringVal(valMap, key) != null ? new BigDecimal(valMap.get(key).toString()) : null;
    }

    public static String getMapStringVal2(Map<String, String> valMap, String key) {
        return valMap.get(key) != null ? valMap.get(key).toString() : null;
    }

    public static boolean equals(Object obj1, Object... objs) {
        if (obj1 == null && objs == null) {
            return true;
        }
        if (objs == null) {
            return false;
        }
        for (Object obj : objs) {
            if (Objects.equals(obj1, obj)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否全部相同
     * @param obj1
     * @param objs
     * @return
     */
    public static boolean AllEquals(Object obj1, Object... objs) {
        if (obj1 == null && objs == null) {
            return true;
        }
        if (objs == null) {
            return false;
        }
        for (Object obj : objs) {
            if (!Objects.equals(obj1, obj)) {
                return false;
            }
            continue;
        }
        return true;
    }

    public static String getDate(String sformat) {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat(sformat);
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    public static String getRandomNum(int num) {
        String numStr = "";
        for (int i = 0; i < num; i++) {
            numStr += (int) (10 * (Math.random()));
        }
        return numStr;
    }

    /**
     * 生成id
     *
     * @return
     */
    public static String getGeneratID() {
        String sformat = "yyyyMMddHHmmss";
        int num = 3;
        String idStr = getDate(sformat) + getRandomNum(num);
        return idStr;
    }

    /**
     * 执行js表达式
     *
     * @param expression
     * @param params
     * @return
     */
    public static Object executeExpression(String expression, Map<String, Object> params) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        if (params != null) {
            for (Map.Entry<String, Object> tmpMap : params.entrySet()) {
                engine.put(tmpMap.getKey(), tmpMap.getValue());
            }
        }
        Object result = null;
        try {
            result = engine.eval(expression);
        } catch (ScriptException e) {
            System.out.println("excuteExpression Exception! expression:" + expression + "\nparams:" + params);
            // top.ibase4j.core.util.LogUtil.error(e);
        }

        return result;
    }

    public static boolean executeBooleanExpression(String expression, Map<String, Object> params) {
        Object result = executeExpression(expression, params);
        if (result instanceof Boolean && (Boolean) result) {
            return (Boolean) result;
        }
        return false;
    }

    /**
     * 驼峰转下划线
     */
    public static String humpToLine2(String str) {
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 生成随机数
     *
     * @return
     */
    public static Integer getRandom() {
        Random random = new Random();
        return random.nextInt(50 - 20 + 1) + 20;
    }


    public static String getFormatNum(Integer numLength) {
        StringBuilder sb = new StringBuilder();
        if (isValidId(numLength)) {
            for (int i = 0; i < numLength; i++) {
                sb.append("0");
            }
        }
        return sb.toString();
    }


    /**
     * 提取首字母
     *
     * @param oldStr
     * @return 小写首字母
     */
    public static String extractTheFirstLetter(String oldStr) {
        //包含汉字缩写
        //判断首字母类型
        char[] chars = oldStr.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            String str = String.valueOf(chars[i]);
            boolean isCH = determineWhetherIsCH(str);
            if (isCH) {
                stringBuilder.append(CHToPyUtil.ch2py(str).substring(0, 1).toLowerCase());
            } else {
                stringBuilder.append(str.toLowerCase());
            }
        }
        return stringBuilder.toString();
    }

    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("[0-9]+");
        return pattern.matcher(str).matches();
    }

    public static boolean determineWhetherIsCH(String countname) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(countname);
        if (m.find()) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        String date = DateUtils.getDate();
        System.out.println(date);
    }

}
